home *** CD-ROM | disk | FTP | other *** search
- /*
- * (c)Copyright 1992-1997 Obvious Implementations Corp. Redistribution and
- * use is allowed under the terms of the DICE-LICENSE FILE,
- * DICE-LICENSE.TXT.
- */
- #include "vmake.h"
-
- struct Gadget *oldgad;
-
- Prototype void handle_hit(struct Gadget *gad,int shift, int doubleclick);
- Prototype void set_cyc_state(struct G_CYCLE *cyc,struct G_VALUE *val);
- Prototype void handle_list(struct G_LIST *list,struct Gadget *gad,int class,char *buf, int doubleclick);
- Prototype void redraw_gadget(struct Gadget *gad);
- Prototype void recalc_prop(struct G_LIST *list,UWORD *body,UWORD *sltop);
- Prototype int newpos(struct G_LIST *list,int spos,struct G_ENTRY *ent);
- Prototype void set_gadlist(struct GADLIST *gadlist,int state);
- Prototype void set_gadgets(int state);
- Prototype int get_work_filename(char *gfname, int spat);
- Prototype void mark_clean(void);
- Prototype int test_dirty(void);
-
- /***********************************************************************************
- * Procedure: handle_hit
- * Synopsis: handle_hit(gadget, shift, doubleclick);
- * Purpose: Handle the processing for the hit on a gadget.
- ***********************************************************************************/
- void handle_hit(struct Gadget *gad,
- int shift,
- int doubleclick
- )
- {
- struct G_OBJECT *obj;
-
- obj = (struct G_OBJECT *)gad->UserData;
- /* Ignore any hits on disabled gadgets */
- if ((gad->Flags & GADGHIGHBITS) == GADGHNONE) return;
-
- if (doubleclick)
- {
- if (oldgad != gad)
- doubleclick = 0;
- }
- else
- oldgad = gad;
-
- #ifdef DBG_JGM
- printf("Double click state = %d\n", doubleclick);
- #endif
-
- switch(obj->class)
- {
- case CLASS_STRING:
- break;
- case CLASS_CYCLE:
- {
- /* We need to advance the string to the next state */
- /* When we refresh the gadget, we need to first blank it out */
- struct G_CYCLE *cyc;
- struct G_VALUE *val;
-
- cyc = (struct G_CYCLE *)obj;
- val = cyc->curval;
-
- if (shift)
- {
- for(val = cyc->values;
- (val->next != NULL) && (val->next != cyc->curval);
- val = val->next);
- }
- else
- {
- val = val->next;
- if (val == NULL) val = cyc->values;
- }
- set_cyc_state(cyc, val);
- obj->state |= DIRTY_BIT;
- }
- break;
- case CLASS_CHECK:
- obj->state = ((gad->Flags & SELECTED) != 0) & DIRTY_BIT;
- break;
- case CLASS_LIST:
- handle_list((struct G_LIST *)obj, gad, gad->GadgetID, NULL, doubleclick);
- break;
- case CLASS_BUTTON:
- if (!doubleclick) /* don't edit or compile twice for a double click */
- do_command(global.button[obj->state & STATE_MASK].command);
- break;
- default:
- break;
- }
- }
- /***********************************************************************************
- * Procedure: redraw_gadget
- * Synopsis: redraw_gadget(gadget);
- * Purpose: Rerender a gadget on the screen
- ***********************************************************************************/
- void redraw_gadget(struct Gadget *gad
- )
- {
- SetBPen(global.rp, 0);
- SetAPen(global.rp, 0);
- RectFill( global.rp, gad->LeftEdge + VBAR, gad->TopEdge + HBAR,
- gad->LeftEdge + gad->Width - 1 - VBAR,
- gad->TopEdge + gad->Height - 1 - HBAR);
- RefreshGList( gad, global.window, NULL, 1);
- }
-
- /***********************************************************************************
- * Procedure: set_cyc_state
- * Synopsis: set_cyc_state(cyc,val)
- * Purpose: Set a cycle gadget to a give value
- ***********************************************************************************/
- void set_cyc_state(struct G_CYCLE *cyc,
- struct G_VALUE *val
- )
- {
- struct G_STRING *str;
- struct Gadget *gad;
-
- /* See It is currently being displayed on the screen. If so, we will have to */
- /* do some cleanup work to get it updated. */
- str = cyc->curval->string;
- if ((str != NULL) && (str->base.gadget != NULL))
- {
- /* If there is a string gadget currently in the cycle gadget, we need */
- /* to free it up */
- RemoveGList( global.window, str->base.gadget, 1);
- free_gadget(str->base.gadget);
- }
-
- if (val == NULL) return;
-
- cyc->curval = val;
-
- /* Now, if we are currently displaying the gadget, we need to get it on the */
- /* screen. */
- if (gad = cyc->base.gadget)
- {
- struct IntuiText *itext;
- struct Gadget *strgad;
- int oldpos;
-
- itext = gad->GadgetText->NextText;
- itext->IText = val->title;
-
- strgad = setup_cycle_gadget(gad, itext, val);
-
- oldpos = RemoveGList(global.window, gad, 1);
- AddGList(global.window, gad, oldpos, 1, NULL);
-
- if (strgad) AddGadget( global.window, strgad, 0);
-
- /* Wipe out the inner area of the gadget so that we can redraw it later */
- redraw_gadget(gad);
- if (strgad) redraw_gadget(strgad);
- }
- }
-
- /***********************************************************************************
- * Procedure: handle_list
- * Synopsis: handle_list(list, gadget, int class, buf, doubleclick);
- * Purpose: Handle the processing for the hit on a list gadget.
- ***********************************************************************************/
- void handle_list(struct G_LIST *list,
- struct Gadget *gad,
- int class,
- char *buf,
- int doubleclick
- )
- {
- struct G_ENTRY *ent, *prevent;
- struct PropInfo *pi;
- int expect;
- int docmnd;
- int pos;
- int prevpos;
- int i;
- int oldpos[MAX_LIST];
-
- static int oldpropidx;
-
- expect = docmnd = 0;
- pos = -1; /* used to indicate no valid selection */
- if (list->sel) /* we should expect a valid selection */
- {
- expect = 1;
- pos = list->base.state & STATE_MASK;
- }
- prevpos = pos;
-
- switch(class & CLASS_MASK) /* Isolate class from subclass */
- {
- case CLASS_ADD:
- {
- int nameinbuf = 0;
- /* Note that gad parameter may not be set on entry. In this case */
- /* if buf parm is set, it has name of file to add, otherwise */
- /* request a name. No way to enter a name for Dos 1.3 yet. */
- if (doubleclick) /* Don't put up requester twice */
- return;
- ent = get_mem(sizeof(struct G_ENTRY));
- if (ent == NULL)
- {
- request(1, TEXT_NOMEM, NULL, NULL);
- return;
- }
-
- if (buf)
- if (*buf != '\0')
- {
- strcpy(ent->buf, buf);
- nameinbuf = 1;
- }
- if (!nameinbuf)
- {
- if (get_work_filename(ent->buf, CONFIG_FILES) == 0)
- {
- /* User aborted file request, we need to give up too */
- free_mem(ent, sizeof(struct G_ENTRY));
- global.rexxrc = TEXT_CANCEL; /* It's what happened... */
- return; /* don't mess around with gadgets */
- }
- }
-
- /* we're committed - make sure we select it, whereever we put it */
- expect = 1;
- /* now link the new name into the list */
- if (list->first == NULL)
- {
- int oldpos;
- oldpos = RemoveGList(global.window, list->delgad, 1);
- list->delgad->Flags &= ~GADGDISABLED;
- AddGList(global.window, list->delgad, oldpos, 1, NULL);
- redraw_gadget(list->delgad);
- list->top = list->first = ent;
- pos = 0; /* select the entry we just added */
- }
- else
- {
- if (pos == -1) /* if nothing selected, add at top of */
- pos = 0; /* display - and select it */
- prevent = list->top;
- for (i = 0; (i < pos) && (prevent != NULL); i++)
- prevent = (struct G_ENTRY *)prevent->base.next;
- /* Insert in front of prevent */
- ent->base.next = (struct G_OBJECT *)prevent;
- if (prevent)
- {
- ent->base.prev = prevent->base.prev;
- prevent->base.prev = (struct G_OBJECT *)ent;
- }
- if (ent->base.prev)
- {
- if (list->top == prevent) list->top = ent;
- ent->base.prev->next = (struct G_OBJECT *)ent;
- }
- else
- {
- list->top = list->first = ent;
- }
- expect = 1;
- }
- /* the list has been changed */
- list->base.state |= DIRTY_BIT;
- break;
- }
- case CLASS_DEL:
- if (doubleclick) /* don't delete two objects by mistake... */
- return;
- if (pos == -1) /* nothing selected - don't pick one at random...*/
- return;
- ent = list->top;
- for (i = 0; (i < pos) && (ent != NULL); i++)
- ent = (struct G_ENTRY *)ent->base.next;
- /* We want to delete ent */
- if (ent == NULL) return;
- if (ent->base.next)
- ent->base.next->prev = ent->base.prev;
- if (ent->base.prev)
- ent->base.prev->next = ent->base.next;
- else
- list->first = (struct G_ENTRY *)ent->base.next;
-
- /* Update the base pointer so that we are looking at the right space */
- if (list->top == ent)
- {
- list->top = (struct G_ENTRY *)ent->base.next;
- if (list->top == NULL)
- list->top = (struct G_ENTRY *)ent->base.prev;
- }
- free_mem(ent, sizeof(struct G_ENTRY));
- /* the list has been changed */
- list->base.state |= DIRTY_BIT;
- /* and note that we fall through to set state of del gadget */
- goto dodelgad;
- /* except that we want to leave the next item selected - it */
- /* will have moved up to the display position just vacated. */
- case CLASS_REFRESH:
- expect = 0;
-
- dodelgad:
- {
- int oldpos;
-
- oldpos = RemoveGList(global.window, list->delgad, 1);
- if (list->first == NULL)
- list->delgad->Flags |= GADGDISABLED;
- else
- list->delgad->Flags &= ~GADGDISABLED;
- AddGList(global.window, list->delgad, oldpos, 1, NULL);
- redraw_gadget(list->delgad);
- }
- RefreshGList( list->delgad, global.window, NULL, 5);
- break;
- case CLASS_UP:
- expect = 0; /* trying to move deselects */
- if ((list->top != NULL) && (list->top->base.prev != NULL))
- {
- list->top = (struct G_ENTRY *)list->top->base.prev;
- }
- break;
- case CLASS_DOWN:
- {
- struct G_ENTRY *ent;
- expect = 0; /* trying to move deselects */
- if ((list->top != NULL) && (list->top->base.next != NULL))
- {
- list->top = (struct G_ENTRY *)list->top->base.next;
- }
- ent = list->first;
- i = list->maxent - global.listsize;
- while (ent && i)
- {
- if ((ent = (struct G_ENTRY *)ent->base.next) == list->top)
- break;
- i--;
- }
- if ((i == 0) && (ent != NULL))
- list->top = ent;
- }
- break;
- case CLASS_PROP:
- {
- int maxtop;
- expect = 0; /* trying to move deselects */
- pi = (struct PropInfo *)gad->SpecialInfo;
- maxtop = list->maxent - global.listsize;
- i = (pi->VertPot*(2*maxtop))/MAXBODY;
- i = (i + 1)/ 2; /* rounding for more natural button behavior */
- if (i > maxtop) i = maxtop;
- if ((global.mouseprop) && (i == oldpropidx))
- {
- /* don't want to refresh the list unless the view has */
- /* changed. Have to refresh the prop gadget or it decays */
- /* all over the border. */
- UWORD body, sltop;
- recalc_prop(list, &body, &sltop);
- NewModifyProp(list->slider, global.window, NULL,
- AUTOKNOB | FREEVERT | PROPBORDERLESS,
- 0, sltop, MAXBODY, body, 1L);
- return;
- }
- else
- oldpropidx = i;
- list->top = list->first;
- while((i > 0) && (list->top != NULL))
- {
- list->top = (struct G_ENTRY *)list->top->base.next;
- i--;
- }
- if (list->top == NULL) list->top = list->first;
- }
- break;
- case CLASS_LIST:
- pos = class >> SUBCLASS_OFF;
- expect = 1;
- if (doubleclick)
- docmnd = 1; /* user double clicked on a list entry */
- break;
- case CLASS_SELECT:
- {
- int spos;
- int simplename;
- struct G_ENTRY *ent;
-
- expect = 0; /* signal nothing to select */
- pos = -1; /* nothing selected */
- if (buf == NULL) /* no parameter - nothing to do */
- break;
- if (*buf == '\0') /* empty string not a valid list entry */
- break;
- /* set pathname true if path separators present, false (or */
- /* NULL) otherwise */
- simplename = (strpbrk(buf, ":/") == NULL);
- ent = list->first;
- spos = 0;
- while (ent)
- {
- char *fnp, *tp;
- fnp = ent->buf;
- if (simplename)
- /* want to match simple name - ignore any path in list entry */
- {
- tp = strrchr(ent->buf, '/');
- if (tp == NULL) /* no slash, try for a colon */
- tp = strrchr(ent->buf, ':');
- if (tp != NULL) /* strip off the whole path */
- fnp = tp + 1;
- }
- if (stricmp(fnp, buf))
- {
- /* does not match, step through list */
- ent = (struct G_ENTRY *)ent->base.next;
- spos++;
- }
- else
- break;
- }
- if (ent == NULL) /* didn't find a match in the list */
- break;
- /* we're selected something, now figure out where it goes */
- expect = 1;
- pos = newpos(list, spos, ent);
- }
- break;
- case CLASS_LTOP:
- case CLASS_LBOT:
- int spos;
- struct G_ENTRY *ent;
-
- ent = list->first; /* tricky: not needed when going to bottom */
- if ((class & CLASS_MASK) == CLASS_LTOP)
- spos = 0;
- else
- spos = list->maxent-1;
- expect = 1;
- pos = newpos(list, spos, ent);
- break;
- case CLASS_LUP:
- case CLASS_LDN:
- int spos;
- struct G_ENTRY *ent, *sent;
-
- sent = list->sel;
- if ((class & CLASS_MASK) == CLASS_LUP)
- sent = (struct G_ENTRY *)sent->base.prev;
- else
- sent = (struct G_ENTRY *)sent->base.next;
- spos = 0;
- ent = list->first;
- while (ent)
- {
- if (ent == sent)
- break;
- ent = (struct G_ENTRY *)ent->base.next;
- spos++;
- }
- expect = 1;
- pos = newpos(list, spos, ent);
- break;
- default:
- printf("Unexpected list gadget class 0x%x\n", class);
- break;
- }
-
- list->sel = NULL; /* turn off selection & see if we reselect */
-
- gad = list->base.gadget;
-
- if (expect)
- {
- /* Make sure that we are actually in a position to enable the */
- /* requested string gadget. If not, just ignore the request */
- /* Start from the top of the display and see if there's an */
- /* entry at the requested position. */
- ent = list->top;
- for(i = pos; ent && (i > 0); i--)
- ent = (struct G_ENTRY *)ent->base.next;
-
- if (ent)
- {
- list->sel = ent;
- }
- else
- {
- pos = -1;
- /* clear out the selected string gadget */
- list->base.state = list->base.state & DIRTY_BIT;
- }
- }
- else
- {
- pos = -1;
- }
- /* point to selected entry gadget if any */
- list->base.state = (list->base.state & DIRTY_BIT) + (pos & STATE_MASK);
-
- /* handle refreshing of LIST hit differently to reduce screen flash */
- /* and improve response to double click (remove gadget for less time) */
- if ((class & CLASS_MASK) != CLASS_LIST)
- {
- for(i = global.listsize-1; i >= 0; i--)
- {
- oldpos[i] = RemoveGList(global.window, list->btngad[i], 2);
- }
- reset_list_object(list, pos);
-
- /* Wipe out the inner area of the gadget so that we can redraw it later */
- redraw_gadget(gad);
-
- for(i = 0; i < global.listsize; i++)
- {
- AddGList(global.window, list->btngad[i], oldpos[i], 2, NULL);
- RefreshGList( list->btngad[i], global.window, NULL, 2);
- }
- }
- else
- {
- if ((prevpos != -1) && (prevpos != pos))
- /* redraw old button gadget to wipe out the border */
- {
- int oldpos;
- struct Gadget *bgad = list->btngad[prevpos];
- oldpos = RemoveGList(global.window, list->btngad[prevpos], 2);
- list->strgad[prevpos]->GadgetRender = NULL;
- /* standard redraw() misses the edges of the border *sigh* */
- /* this sizing is a bit slimy and ad hoc but it seems to work... */
- SetBPen(global.rp, 0);
- SetAPen(global.rp, 0);
- RectFill( global.rp, bgad->LeftEdge, bgad->TopEdge + 1,
- bgad->LeftEdge + bgad->Width - 1,
- bgad->TopEdge + bgad->Height - 2 + global.listextra);
- AddGList(global.window, list->btngad[prevpos], oldpos, 2, NULL);
- RefreshGList( list->btngad[prevpos], global.window, NULL, 2);
- }
- if (pos != -1)
- /* draw border for newly selected list gadget */
- {
- int oldpos;
- oldpos = RemoveGList(global.window, list->btngad[pos], 2);
- list->strgad[pos]->GadgetRender = list->sborder;
- AddGList(global.window, list->btngad[pos], oldpos, 2, NULL);
- RefreshGList( list->btngad[pos], global.window, NULL, 2);
- }
- }
-
- /* remove to prevent typing into gadget
- if (pos >= 0)
- ActivateGadget(list->strgad[pos], global.window, NULL);
- */
-
- {
- UWORD body, sltop;
- recalc_prop(list, &body, &sltop);
- NewModifyProp(list->slider, global.window, NULL,
- AUTOKNOB | FREEVERT | PROPBORDERLESS,
- 0, sltop, MAXBODY, body, 1L);
- }
-
- if (docmnd && list->sel) /* double clicked on a valid entry */
- do_command(global.text[CONFIG_DCLICK]);
- }
- /***********************************************************************************
- * Procedure: recalc_prop
- * Synopsis: recalc_prop(list)
- * Purpose: Calculate the appropriate BODY and TOP values for a List Prop gadget
- ***********************************************************************************/
- void recalc_prop(struct G_LIST *list,
- UWORD *body, UWORD *sltop
- )
- {
- int count, top, maxtop;
- struct G_ENTRY *ent;
-
- count = top = 0;
- ent = list->first;
-
- while(ent != NULL)
- {
- if (ent == list->top) top = count;
- count++;
- ent = (struct G_ENTRY *)ent->base.next;
- }
-
- list->maxent = count;
-
- *body = MAXBODY;
-
- *sltop = 0;
- if (count > global.listsize)
- {
- *body = (MAXBODY * global.listsize) / count;
- maxtop = count - global.listsize;
- if (top > maxtop) top = maxtop;
- *sltop = (MAXBODY * top) / maxtop;
- }
-
- }
- /***********************************************************************************
- * Procedure: newpos
- * Synopsis: newpos(list, spos, ent)
- * Purpose: set display position for a new list selection
- * caller knows both entry & index - why recalculate?
- ***********************************************************************************/
- int newpos(struct G_LIST *list,int spos,struct G_ENTRY *ent)
- {
- int j, pos, dtop, maxtop;
- struct G_ENTRY *dent;
-
- maxtop = list->maxent - global.listsize;
-
- /* Now find the index of the top of the visible display */
- dent = list->first;
- dtop = 0;
- while (dent)
- {
- if (dent == list->top)
- /* We've reached the start of the visible display */
- break;
- else
- /* keep counting */
- {
- dent = (struct G_ENTRY *)dent->base.next;
- dtop++;
- }
- }
- if ((spos >= dtop) && ((spos - dtop) < global.listsize))
- /* selection is within range of display */
- {
- pos = spos - dtop;
- }
- else if (spos <= maxtop)
- /* can move display to start with selected item */
- {
- list->top = ent;
- pos = 0;
- }
- else
- /* find the lowest possible entry for the top of the display */
- {
- for (j = dtop; j < maxtop; j++)
- list->top = (struct G_ENTRY *)list->top->base.next;
- pos = spos - maxtop;
- }
-
- return pos;
- }
- /***********************************************************************************
- * Procedure: set_gadlist
- * Synopsis: set_gadlist(gadlist,on/off)
- * Purpose: Enable or Disable all the gadgets in a list
- ***********************************************************************************/
- void set_gadlist(struct GADLIST *gadlist,
- int state
- )
- {
- struct Gadget *gad;
- struct G_CYCLE *cyc;
- int count;
-
- if ((global.window == NULL) ||
- (gadlist == NULL))
- return;
-
- if (state)
- {
- AddGList( global.window, gadlist->gadgets, 30000, gadlist->count, NULL);
- }
- else
- {
- RemoveGList(global.window, gadlist->gadgets, gadlist->count);
- }
-
- for(gad = gadlist->gadgets, count=gadlist->count;
- gad && count;
- gad = gad->NextGadget, count--)
- {
- cyc = (struct G_CYCLE *)gad->UserData;
-
- if ((cyc->base.class & CLASS_MASK) == CLASS_CYCLE)
- {
- set_cyc_state(cyc, state ? cyc->curval : NULL);
- }
- else if (state)
- {
- if ((cyc->base.class & CLASS_MASK) == CLASS_LIST)
- {
- if (gad == cyc->base.gadget)
- handle_list((struct G_LIST *)cyc, NULL, CLASS_REFRESH, NULL, 0);
- }
- else
- {
- RefreshGList(gad, global.window, NULL, 1);
- }
- }
- }
- }
-
- /***********************************************************************************
- * Procedure: set_gadgets
- * Synopsis: set_gadgets(on/off)
- * Purpose: Enable or Disable all gadgets
- ***********************************************************************************/
- void set_gadgets(int state)
- {
- static int gadliststate;
-
- if (state == gadliststate)
- /* adding or removing twice in a row causes problems */
- return;
- else
- {
- gadliststate = state;
- set_gadlist(global.gadlist, state);
- }
- }
-
- /***********************************************************************************
- * Procedure: get_work_filename
- * Synopsis: type = get_work_filename(gfname, spat)
- * Purpose: Parse out a file descriptor and return a type for that name
- * gfname points to a buffer to receive the name.
- * spat is the index of a search pattern entry in global.text[]
- ***********************************************************************************/
- int get_work_filename(char *gfname, int spat)
- {
- char *p;
- int len;
- int n;
-
- if (global.inrexx)
- {
- /* whoever called us should have had a filename parameter */
- global.rexxrc = TEXT_BADPARM;
- return 0;
- }
-
- if (global.freq == NULL) return(0);
-
- set_workdir();
- set_busy();
-
- if (AslBase != NULL)
- {
- struct TagItem taglist[9];
-
- n = 0;
-
- taglist[n ].ti_Tag = ASL_Pattern;
- taglist[n++].ti_Data = (ULONG)global.text[spat];
-
- taglist[n ].ti_Tag = ASL_File;
- taglist[n++].ti_Data = (ULONG)"";
-
- taglist[n ].ti_Tag = ASL_Dir;
- taglist[n++].ti_Data = (ULONG)"";
-
- taglist[n ].ti_Tag = ASL_Window;
- taglist[n++].ti_Data = (ULONG)global.window;
-
- #ifdef ASLFR_DoSaveMode
- taglist[n ].ti_Tag = ASLFR_DoSaveMode;
- taglist[n++].ti_Data = FALSE;
- #endif
-
- #ifdef ASLFR_DoPatterns
- taglist[n ].ti_Tag = ASLFR_DoPatterns;
- taglist[n++].ti_Data = TRUE;
- #endif
-
- #ifdef ASLFR_RejectIcons
- taglist[n ].ti_Tag = ASLFR_RejectIcons;
- taglist[n++].ti_Data = TRUE;
- #endif
-
- #ifdef ASLFR_SleepWindow
- taglist[n ].ti_Tag = ASLFR_SleepWindow;
- taglist[n++].ti_Data = TRUE;
- #endif
-
- taglist[n ].ti_Tag = TAG_DONE;
- taglist[n++].ti_Data = 0;
-
- if (!AslRequest( (APTR)global.freq, taglist))
- {
- set_idle();
- return(0);
- }
- }
- else
- {
- /* We must have arp.library (otherwise we wouldn't have a file */
- /* Requester structure.) */
- global.freq->rf_Dir[0] = 0;
- global.freq->rf_File[0] = 0;
- if (!ArpFileRequest( global.freq ))
- {
- set_idle();
- return(0);
- }
- }
- set_idle();
-
- n = strlen(global.freq->rf_Dir);
- if (n > 255) n = 255;
- p = gfname;
- memcpy(p, global.freq->rf_Dir, n);
- p += n;
-
- if ((n > 0) && (p[-1] != ':'))
- {
- *p++ = '/';
- n++;
- }
- len = strlen(global.freq->rf_File);
- if (len == 0) return 0; /* null name string equivalent to cancelling */
- if ((n + len) > 255) len = 255-n;
- strncpy(p, global.freq->rf_File, len);
- p[len] = 0;
-
- if (!stricmp(gfname, "ENV"))
- return(FILE_ENV);
-
- len = strlen(gfname);
- p = gfname + strlen(gfname);
-
- if (len < 2)
- return(FILE_OPTIONS);
-
- if ((len >= 7) && (!stricmp(p-7, "DCCOPTS")))
- return(FILE_OPTIONS);
-
- if ((len >= 9) && (!stricmp(p-9, "DMAKEFILE")))
- return(FILE_DMAKEFILE);
-
- if (!stricmp(p-2, ".H"))
- return(FILE_C);
-
- if (!stricmp(p-2, ".C"))
- return(FILE_C);
-
- return(FILE_OPTIONS);
- }
-
-
- /***********************************************************************************
- * Procedure: mark_clean
- * Synopsis: mark_clean()
- * Purpose: reset DIRTY bit for all string objects
- ***********************************************************************************/
- void mark_clean(void)
- {
- struct G_OBJECT *obj;
- struct G_STRING *strobj;
- #define cycobj ((struct G_CYCLE *)obj)
-
- obj = global.objects;
- while (obj)
- {
- obj->state &= STATE_MASK; /* reset dirt bit for this object */
- if (obj->class == CLASS_STRING)
- strobj = (struct G_STRING *)obj;
- else
- /* see if it's a cycle which might have a string sub-object */
- {
- if (obj->class == CLASS_CYCLE)
- /* strobj may end up NULL. That's fine */
- strobj = cycobj->curval->string;
- else
- strobj = NULL;
- }
- if (strobj)
- {
- /* checkpoint present string - safely */
- strncpy(strobj->clean_buf, strobj->buf, MAX_STRING);
- }
- obj = obj->next;
- }
- global.dirtysym = 0; /* flags externally defined symbols */
- #define cycobj
- }
- /***********************************************************************************
- * Procedure: test_dirty()
- * Synopsis: bool = test_dirty()
- * Purpose: set dirty bits for string objects and return true if any dirty
- * objects are found
- ***********************************************************************************/
- int test_dirty(void)
- {
- struct G_OBJECT *obj;
- struct G_STRING *strobj;
- int dirty = 0;
-
- obj = global.objects;
- while (obj)
- /* we want to look at everything, not exit on the first dirty object */
- /* because this routine also flags any dirty string (sub)objects */
- {
- if (obj->class == CLASS_STRING)
- strobj = (struct G_STRING *)obj;
- else
- {
- /* if it's a cycle, and we haven't changed the pointer, and this */
- /* entry in the cycle has a string gadget, see if the string has */
- /* changed. */
- if ((obj->class == CLASS_CYCLE) && !(obj->state & DIRTY_BIT))
- strobj = ((struct G_CYCLE *)obj)->curval->string;
- else
- strobj = NULL;
- }
- if (strobj)
- if (strcmp(strobj->buf, strobj->clean_buf) != 0)
- /* not the same as the snapshot last time mark_clean() went by */
- obj->state |= DIRTY_BIT; /* easy for anyone else to see now */
-
- /* whether string object or not, see if it's dirty */
- if (obj->state & DIRTY_BIT)
- dirty = DOSTRUE;
- obj = obj->next;
- }
-
- if (global.dirtysym) /* has user set any private symbols? */
- dirty = DOSTRUE;
-
- return dirty;
- }
-